package com.sniper.web.action;

import com.sniper.data.Protocol;
import com.sniper.model.Site;
import com.sniper.utils.HttpRequestUtils;
import com.sniper.utils.ValidateUtil;
import com.sniper.web.freemarker.FreeMarkerUtil;
import com.sniper.web.freemarker.FreeMarkerViewUtil;
import com.sniper.web.redis.RedisConnUtil;
import com.sniper.web.utils.BaseHref;
import com.sniper.web.utils.SystemConfigUtil;
import freemarker.template.TemplateHashModel;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.cache.CacheManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.context.support.ResourceBundleMessageSource;
import org.springframework.web.servlet.view.UrlBasedViewResolver;
import redis.clients.jedis.Jedis;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.time.ZoneId;
import java.util.Date;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public abstract class RootController {

    /**
     * 记录运行时间
     */

    @Autowired
    protected ResourceBundleMessageSource messageSource;

    protected static final Logger LOGGER = LoggerFactory.getLogger(RootController.class);
    /**
     * 保存一些基本信息
     */
    protected BaseHref baseHref = new BaseHref();

    /**
     * redis缓存
     */
    @Resource
    protected RedisConnUtil redisConn;
    /**
     * ehcache缓存
     */
    @Resource(name = "ehCacheManager")
    private CacheManager cacheManager;
    /**
     * 后台地址
     */
    @Value("${adminPath}")
    public String adminPath;

    public static ZoneId zoneId = Protocol.zoneId;

    public String ip;

    /**
     * 默认语言
     */
    protected Locale locale = LocaleContextHolder.getLocale();

    // 执行原始的request方法
    @Autowired
    protected HttpServletRequest request;

    protected static final Map<String, String> RIGHT_TYPE = new HashMap<>();

    static {
        RIGHT_TYPE.put("admin", "后台");
    }


    /**
     * freemarker 一些函数组件
     */
    public static final TemplateHashModel hashModel = FreeMarkerUtil.getFreeMarkerStaticModel(FreeMarkerViewUtil.class);
    /**
     * 专题接口
     */

    /**
     * 站点模板
     */
    protected static final Site site = new Site();

    @Value("${yiyun.oauth2.appid}")
    public String yiyunOauth2Appid;
    @Value("${yiyun.oauth2.appSecret}")
    public String yiyunOauth2AppSecret;
    @Value("${yiyun.oauth2.url}")
    public String getYiyunOauth2Url;

    /**
     * 在系统初始化的时候加载
     */
    public RootController() {
        // 这里可以做一些对类变量做一些永久赋值的操作,因为这里只会执行一次
    }


    /**
     * 获取网站完整域名
     *
     * @return
     */
    public String getBasePath() {
        String basePath = request.getScheme() + "://" + request.getServerName();
        if (request.getServerPort() != 80) {
            basePath += ":" + request.getServerPort();
        }
        basePath += request.getContextPath();

        return basePath;
    }

    /**
     * 所有方法之前必须执行的方法 这里一般做一些赋值操作，不可过度操作数据 否则会拖慢系统
     *
     * @param map
     */

    public void init(Map<String, Object> map) {


        if (HttpRequestUtils.isAjax(request)) {
            return;
        }
        ip = HttpRequestUtils.getRealIP(request);
        // 后台路径
        baseHref.setAdminPath(adminPath);
        baseHref.setIp(ip);
        // 带有后缀的域名
        baseHref.setBaseHref(getBasePath() + "/");
        // 无后缀域名
        baseHref.setWebUrl(getBasePath());
        // 系统配置数据
        map.put("systemConfig", SystemConfigUtil.getSystemConfig());
        map.put("baseHref", baseHref);
        // 处理freemarker模板助手
        map.put("freeMarkerUtils", hashModel);

        site.setName("default");
    }

    protected String redirect(String dir) {
        return UrlBasedViewResolver.REDIRECT_URL_PREFIX + dir;
    }

    protected String forward(String dir) {
        return dir;
    }

    protected String forward(String dir, String prefix) {
        return prefix + dir;
    }

    /**
     * 检查来源是否是机器人 判断原理 是否是永远相同的浏览器信息，因为机器来源的浏览器信息一般都永远一样 检查短时间内相同ip，相同浏览器信息访问
     *
     * @return
     */
    public boolean isRobot() {

        Jedis jedis = redisConn.getJedis();

        try {
            String ip = HttpRequestUtils.getRealIP(request);
            StringBuilder builder = new StringBuilder();
            builder.append("非法访问:");
            builder.append("IP:");
            builder.append(ip);
            builder.append(",");
            builder.append("时间:");
            builder.append(new Date());
            String userAgent = request.getHeader("user-agent");
            String robotPreg = "bot|spider|crawl|nutch|lycos|robozilla|slurp|search|seek|archive|baidu|google";
            if (!ValidateUtil.isValid(userAgent)) {
                LOGGER.error(builder.toString());
                return true;
            }
            Pattern pattern = Pattern.compile(robotPreg);
            Matcher matcher = pattern.matcher(userAgent);
            if (matcher.find()) {
                LOGGER.error(builder.toString());
                return true;
            }

            HttpSession session = request.getSession();
            if (session == null) {
                return true;
            }
            String sessionId = session.getId();
            sessionId = "robot:" + sessionId;
            // 用户访问记录
            int countInt = 0;
            // 一定时间内的访问次数
            int maxRobotCount = SystemConfigUtil.getInt("maxRobotCount");
            if (maxRobotCount == 0) {
                maxRobotCount = 3;
            }
            // 如果用户之前来访问过
            if (jedis.exists(sessionId)) {
                String count = jedis.get(sessionId);
                if (StringUtils.isNotBlank(count)) {
                    count = "0";
                }
                countInt = Integer.parseInt(count);
                if (countInt > maxRobotCount) {
                    // 添加ip黑名单
                    LOGGER.error(builder.toString());
                    return true;
                } else {
                    countInt++;
                }
            }
            jedis.set(sessionId, String.valueOf(countInt));
            // 设置访问频率3/2000访问
            jedis.pexpire(sessionId, 2000L);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            redisConn.close(jedis);
        }
        return false;
    }
}